package com.sk.ccflower.lib.util.json;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import com.sk.ccflower.lib.util.JSONUtil;

/**
 * <p>Java배열로 이루어진 JSON 배열을 나타내는 클래스.</p>
 * <p>JSON의 배열은 서로 다른 자료형으로 구성될 수있다.
 * JSON의 Java 자료형으로 바꾼다면 Java에서는 {@link List}가 적절할 것이다.</p>
 * <p>이 클래스는 Java객체를 JSON으로 변환하는 상황에서 주로 사용될 것이다.</p>  
 * @author dagui
 *
 */
public class JSONArray extends JSONObject implements Iterable<Object> {

	private static final long serialVersionUID = -3750429445266078508L;

	private Object array;
	
	/*
	 * constructors
	 */

	public JSONArray(Object value) {
		this.array = value;
	}

	public <T> JSONArray(T[] value) {
		this.array = value;
	}

	/*
	 * implements JSONObject
	 */
	
	@Override
	public void writeJSON(Writer out) throws IOException {
		JSONUtil.writeJSON(array, out);
	}

	@Override
	public Object getValue() {
		return array;
	}
	
	/*
	 * imitate java.util.Collection
	 */

	/**
	 * 순회를 위한 {@link Iterator}를 리턴한다.
	 * @see Iterable#iterator()
	 */
	public Iterator<Object> iterator() {
		return new Iterator<Object>() {

			private int index = 0;

			public boolean hasNext() {
				return (index < Array.getLength(array));
			}

			public Object next() {
				if (index < Array.getLength(array))
					return Array.get(array, index++);
				else
					throw new NoSuchElementException("iteration has no more elements");
			}

			public void remove() {
				throw new UnsupportedOperationException("this iterator is read-only");
			}
		};
	}

	/*
	 * imitate java.util.Collection
	 */

	/**
	 * 배열을 리턴한다.
	 * @see Collection#toArray()
	 */
	public Object[] toArray() {
		return (Object[])array;
	}

	/**
	 * 배열을 리턴한다.
	 * @see Collection#toArray(Object[])
	 */
	@SuppressWarnings("unchecked")
	public <T> T[] toArray(T[] a) {
		int length = Array.getLength(array);
		Class<?> arrayClass = a.getClass();
		T[] newArray = (T[])Array.newInstance(arrayClass, length);
		
		for (int i = 0; i < length; i++)
			newArray[i]	= (T)Array.get(array, i);

		return newArray;
	}

}
